{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "#!/usr/bin/python\n",
    "# find . -name '.DS_Store' -type f -delete\n",
    "# Chulwoo Pack\n",
    "\n",
    "import sys\n",
    "import os\n",
    "from page import Page\n",
    "\n",
    "SHOW_STEPS = True    # change this to false if you just want to see the final output for each page.\n",
    "SAVE_OUTPUT = True\n",
    "SAVE_DOCSTRUM = True\n",
    "\n",
    "inputFolder = os.path.join('images')\n",
    "outputFolder = os.path.join('output')\n",
    "\n",
    "    \n",
    "inputPath = os.path.join(inputFolder, os.listdir(inputFolder)[0])\n",
    "outputPath = os.path.join(outputFolder, os.listdir(inputFolder)[0])\n",
    "\n",
    "page = Page(inputPath, SHOW_STEPS, SAVE_DOCSTRUM)\n",
    "#page = Page(inputPath, SHOW_STEPS)\n",
    "    \n",
    "if SAVE_OUTPUT:\n",
    "    page.save(outputPath)  # save a copy of what is displayed. Used for getting images for the paper.\n",
    "    \n",
    "page.show((800, 800))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.00\t0.00\timages/local_skew.jpg\n",
      "Total  807  characters are found.\n",
      "0.05\t0.05\tgot characters\n"
     ]
    },
    {
     "data": {
      "image/png": "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\nPbbWAAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x1103bc6d0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Total 3228 all NNs\n",
      "('average NN distance: ', 13.860444182118746)\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x118b7cb50>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Total 1674 hor NNs\n",
      "Distance peaks: [4, 14, 24]\n",
      "average NN horizontal distance: 13.81\n",
      "\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n9gAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x118cfbd90>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Total 385 ver NNs\n",
      "Distance peaks: [18, 4]\n",
      "average NN vertical distance: 17.36\n",
      "\n",
      "1.02\t0.97\tgot words & tuples\n",
      "Total  184  words are found.\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n/wezurQS7ejmuwAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x118e5fb50>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXoAAAD8CAYAAAB5Pm/hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAEq1JREFUeJzt3X+o3fddx/Hny7RW2Sam9BqyJDMpZEI6WAaXKExHXdcl\nTjGt6MjAkT8m2SCOiQNp9s+iECjinCB2krmy4I+FgI6GOSdpnI6BLLudWdekC73aliakyd2GuIFE\nm7794367Hbt7c86555ycez95PuBwvt/P9/s93/fnnvt93c/9nu85J1WFJKldPzLtAiRJk2XQS1Lj\nDHpJapxBL0mNM+glqXEGvSQ1zqCXpMYZ9JLUOINekhp327QLALjrrrtq69at0y5DktaUJ5544ltV\nNdNvvVUR9Fu3bmVubm7aZUjSmpLk+UHW89SNJDXOoJekxg0c9EnWJfm3JJ/r5u9McirJM939+p51\nDyWZT3Ihye5JFC5JGswwI/oPAU/3zD8EnK6q7cDpbp4kO4B9wD3AHuCRJOvGU64kaVgDBX2SzcAv\nA3/R07wXONZNHwMe6Gk/XlXXqupZYB7YNZ5yJUnDGnRE/yfA7wEv97RtqKrL3fSLwIZuehPwQs96\nF7s2SdIU9A36JL8CXK2qJ5Zbpxa/pmqor6pKciDJXJK5hYWFYTaVJA1hkBH9W4FfTfIccBx4e5K/\nAq4k2QjQ3V/t1r8EbOnZfnPX9v9U1dGqmq2q2ZmZvtf7S5JWqG/QV9WhqtpcVVtZfJH1n6rqN4GT\nwP5utf3AY930SWBfkjuSbAO2A2fGXrkkaSCjXEf/MHB/kmeAd3TzVNU54ARwHvgCcLCqro9aqDQt\nhw9PuwJpNEN9BEJV/TPwz930t4H7llnvCHBkxNokSWPgO2MlqXEGvSQ1zqCXpMYZ9JLUOINekhpn\n0EtS4wx6SWqcQS9JjTPoJalxBr0kNc6gl6TGGfSS1DiDXpIaZ9BLUuMMeklqnEEvSY0z6CWpcX2D\nPsmPJTmT5OtJziX5/a79cJJLSc52t3f1bHMoyXySC0l2T7IDkqQbG+SrBK8Bb6+q7yW5Hfhykn/o\nln28qv6od+UkO1j8EvF7gNcDjyd5o98bK0nT0XdEX4u+183e3t3qBpvsBY5X1bWqehaYB3aNXKkk\naUUGOkefZF2Ss8BV4FRVfaVb9MEkTyZ5NMn6rm0T8ELP5he7NknSFAwU9FV1vap2ApuBXUneBHwC\nuBvYCVwGPjbMjpMcSDKXZG5hYWHIsiVJgxrqqpuq+k/gi8CeqrrS/QF4GfgkPzg9cwnY0rPZ5q7t\n1Y91tKpmq2p2ZmZmZdVLkvoa5KqbmSQ/2U3/OHA/8M0kG3tWexB4qps+CexLckeSbcB24Mx4y5Yk\nDWqQq242AseSrGPxD8OJqvpckr9MspPFF2afA94PUFXnkpwAzgMvAQe94kaSpqdv0FfVk8Bblmh/\n7w22OQIcGa00SdI4+M5YSWqcQS9JjTPoJalxBr0kNc6gl6TGGfSS1DiDXpIaZ9BLUuMMeklqnEEv\nSY0z6CWpcQa9JDXOoJekxhn0ktQ4g16SGmfQS1LjDHpJatwg3xn7Y0nOJPl6knNJfr9rvzPJqSTP\ndPfre7Y5lGQ+yYUkuyfZAUnSjQ0yor8GvL2q3gzsBPYk+TngIeB0VW0HTnfzJNkB7APuAfYAj3Tf\nNytJmoK+QV+LvtfN3t7dCtgLHOvajwEPdNN7geNVda2qngXmgV1jrVqSNLCBztEnWZfkLHAVOFVV\nXwE2VNXlbpUXgQ3d9CbghZ7NL3ZtkqQpGCjoq+p6Ve0ENgO7krzpVcuLxVH+wJIcSDKXZG5hYWGY\nTSVJQxjqqpuq+k/giyyee7+SZCNAd3+1W+0SsKVns81d26sf62hVzVbV7MzMzEpqlyQNYJCrbmaS\n/GQ3/ePA/cA3gZPA/m61/cBj3fRJYF+SO5JsA7YDZ8ZduCRpMLcNsM5G4Fh35cyPACeq6nNJ/hU4\nkeR9wPPAuwGq6lySE8B54CXgYFVdn0z5kqR++gZ9VT0JvGWJ9m8D9y2zzRHgyMjVSZJG5jtjJalx\nBr0kNc6gl6TGGfSS1DiDXpIaZ9BLUuMMeklqnEEvSY0z6CWpcQa9JDXOoJekxhn0ktQ4g16SGmfQ\nS1LjDHpJapxBL0mNM+glqXEGvSQ1bpAvB9+S5ItJzic5l+RDXfvhJJeSnO1u7+rZ5lCS+SQXkuye\nZAckSTc2yJeDvwR8uKq+luR1wBNJTnXLPl5Vf9S7cpIdwD7gHuD1wONJ3ugXhEvSdPQd0VfV5ar6\nWjf9XeBpYNMNNtkLHK+qa1X1LDAP7BpHsZKk4Q11jj7JVuAtwFe6pg8meTLJo0nWd22bgBd6NrvI\nEn8YkhxIMpdkbmFhYejCJUmDGTjok7wW+Fvgd6rqv4BPAHcDO4HLwMeG2XFVHa2q2aqanZmZGWZT\nSdIQBgr6JLezGPJ/XVV/B1BVV6rqelW9DHySH5yeuQRs6dl8c9cmSZqCQa66CfAp4Omq+uOe9o09\nqz0IPNVNnwT2JbkjyTZgO3BmfCVLkoYxyFU3bwXeC3wjydmu7SPAe5LsBAp4Dng/QFWdS3ICOM/i\nFTsHveJGkqanb9BX1ZeBLLHo8zfY5ghwZIS6JElj4jtjJalxBr0kNc6gl6TGGfSS1DiDXpIaZ9BL\nUuMMeklqnEEvSY0z6CWpcQa9JDXOoJekxhn0ktQ4g16SGmfQS1LjDHpJapxBL0mNM+glqXGDfGfs\nliRfTHI+ybkkH+ra70xyKskz3f36nm0OJZlPciHJ7kl2QJJ0Y4OM6F8CPlxVO4CfAw4m2QE8BJyu\nqu3A6W6ebtk+4B5gD/BIknWTKF6S1F/foK+qy1X1tW76u8DTwCZgL3CsW+0Y8EA3vRc4XlXXqupZ\nYB7YNe7CJUmDGeocfZKtwFuArwAbqupyt+hFYEM3vQl4oWezi12bJGkKBg76JK8F/hb4nar6r95l\nVVVADbPjJAeSzCWZW1hYGGZTSdIQBgr6JLezGPJ/XVV/1zVfSbKxW74RuNq1XwK29Gy+uWv7f6rq\naFXNVtXszMzMSuuXJPUxyFU3AT4FPF1Vf9yz6CSwv5veDzzW074vyR1JtgHbgTPjK1mSNIzbBljn\nrcB7gW8kOdu1fQR4GDiR5H3A88C7AarqXJITwHkWr9g5WFXXx165JGkgfYO+qr4MZJnF9y2zzRHg\nyAh1SZLGxHfGSlLjDHpJapxBL0mNM+glqXEGvSQ1zqCXpMYZ9JLUOINekhpn0EtS4wx6SWqcQS9J\njTPoJalxBr0kNc6gl6TGGfSS1DiDXpIaZ9BLUuMG+c7YR5NcTfJUT9vhJJeSnO1u7+pZdijJfJIL\nSXZPqnBJ0mAGGdF/GtizRPvHq2pnd/s8QJIdwD7gnm6bR5KsG1exkqTh9Q36qvoS8J0BH28vcLyq\nrlXVs8A8sGuE+iRJIxrlHP0HkzzZndpZ37VtAl7oWedi1yZJmpKVBv0ngLuBncBl4GPDPkCSA0nm\nkswtLCyssAxJUj8rCvqqulJV16vqZeCT/OD0zCVgS8+qm7u2pR7jaFXNVtXszMzMSsqQJA1gRUGf\nZGPP7IPAK1fknAT2JbkjyTZgO3BmtBIlSaO4rd8KST4D3AvcleQi8FHg3iQ7gQKeA94PUFXnkpwA\nzgMvAQer6vpkSpckDaJv0FfVe5Zo/tQN1j8CHBmlKEnS+PjOWElqnEEvSY0z6CWpcQa9JDXOoJek\nxhn0ktQ4g16SGmfQS1LjDHpJapxBL0mNM+glqXEGvSQ1zqCXpMYZ9JLUOINekhpn0EtS4wx6SWqc\nQS9Jjesb9EkeTXI1yVM9bXcmOZXkme5+fc+yQ0nmk1xIsntShUuSBjPIiP7TwJ5XtT0EnK6q7cDp\nbp4kO4B9wD3dNo8kWTe2aiVJQ+sb9FX1JeA7r2reCxzrpo8BD/S0H6+qa1X1LDAP7BpTrZKkFVjp\nOfoNVXW5m34R2NBNbwJe6FnvYtf2Q5IcSDKXZG5hYWGFZUiS+hn5xdiqKqBWsN3RqpqtqtmZmZlR\ny5AkLWOlQX8lyUaA7v5q134J2NKz3uauTZI0JSsN+pPA/m56P/BYT/u+JHck2QZsB86MVqIkaRS3\n9VshyWeAe4G7klwEPgo8DJxI8j7geeDdAFV1LskJ4DzwEnCwqq5PqHZJ0gD6Bn1VvWeZRfcts/4R\n4MgoRUmSxsd3xkpS4wx6SWqcQS9JjTPoJalxBr0kNc6gl6TGGfSS1DiDXpIaZ9BLUuMMeklqnEEv\nSY0z6CWpcQa9JDXOoJekxhn0ktQ4g16SGmfQS1LjRgr6JM8l+UaSs0nmurY7k5xK8kx3v348pd56\nDh+edgVSW27VY2ocI/pfrKqdVTXbzT8EnK6q7cDpbl6SNCWTOHWzFzjWTR8DHpjAPiTdIg4fvnVH\n4uMyatAX8HiSJ5Ic6No2VNXlbvpFYMOI+5AkjeC2Ebf/+aq6lOSngFNJvtm7sKoqSS21YfeH4QDA\nG97whhHLkCQtZ6QRfVVd6u6vAp8FdgFXkmwE6O6vLrPt0aqararZmZmZUcqQtAxPewhGCPokr0ny\nulemgXcCTwEngf3davuBx0YtUquP4SGtHaOM6DcAX07ydeAM8PdV9QXgYeD+JM8A7+jmJa0SS43y\nVzryH3YbBwjTseJz9FX1H8Cbl2j/NnDfKEVJksbHd8ZqWeMYfTmC083g79mNGfSS1LhbIui98kDS\nreyWCHpJupUZ9JLUOINekhpn0EtS4wx6SZqA1XQBiEEvSY0z6MfsVr6U81bt97RN+nfuVv6dboVB\nL60C4wxTQ1mvZtD34WhGmiyPr8kz6G9xN/MP2c36hMRWOMjQuBj0jZlGOExrn5IGY9CvYa2O+Frt\n1yCW6vekfh4redxb7blppa8G/ZTcageM1Iq1eNyO+uXgGpPVHvyv1HYza+zd1zT2Py036uNS3ww1\nqRpGfex+j3ErPJerxcRG9En2JLmQZD7JQ5Paj1anYYNi0PVX+x/ESRql32vlZzbO34NB+7xWfjaj\nmMiIPsk64M+A+4GLwFeTnKyq85PY37gMO2pca6PMfvXezP4st6+18rPUD1stx8MoV3ZNu/ZJmdSp\nm13AfPe9siQ5DuwFJhL0S/2LP0kr3cckf5lu5X+R1/JBuhZr7mfS79Jtxc38vZ1U0G8CXuiZvwj8\n7IT2NbLlRpXLXQEx6uOPYql/Wcdx5cRaPICW6sNq7sfN/AM/6X21ehpp0PAdNaRv9s8gVTX+B01+\nHdhTVb/Vzb8X+Nmq+u2edQ4AB7rZnwEurHB3dwHfGqHc1cS+rE72ZXWyL/DTVTXTb6VJjegvAVt6\n5jd3bd9XVUeBo6PuKMlcVc2O+jirgX1ZnezL6mRfBjepq26+CmxPsi3JjwL7gJMT2pck6QYmMqKv\nqpeS/Dbwj8A64NGqOjeJfUmSbmxib5iqqs8Dn5/U4/cY+fTPKmJfVif7sjrZlwFN5MVYSdLq4Wfd\nSFLj1mTQJ/mNJOeSvJxktqd9a5L/TnK2u/35NOscxHJ96ZYd6j5C4kKS3dOqcSWSHE5yqee5eNe0\naxpWSx/jkeS5JN/onou5adczjCSPJrma5KmetjuTnEryTHe/fpo1DmqZvkz8WFmTQQ88Bfwa8KUl\nlv17Ve3sbh+4yXWtxJJ9SbKDxauV7gH2AI90Hy2xlny857m4Ga/XjE3Px3j8ErADeE/3nKxlv9g9\nF2vtksRPs3gM9HoIOF1V24HT3fxa8Gl+uC8w4WNlTQZ9VT1dVSt9g9WqcoO+7AWOV9W1qnoWmGfx\noyV0c3z/Yzyq6n+AVz7GQzdZVX0J+M6rmvcCx7rpY8ADN7WoFVqmLxO3JoO+j23dvz//kuQXpl3M\nCJb6GIlNU6plpT6Y5Mnu39U18a91jxZ+/r0KeDzJE9270te6DVV1uZt+EdgwzWLGYKLHyqoN+iSP\nJ3lqiduNRlWXgTdU1U7gd4G/SfITN6fi5a2wL6ten359Argb2Mni8/KxqRarn++Oi18CDiZ527QL\nGpdavHRwLV8+OPFjZdV+8UhVvWMF21wDrnXTTyT5d+CNwFRffFpJXxjgYySmbdB+Jfkk8LkJlzNu\nq/7nP4yqutTdX03yWRZPTS31GtdacSXJxqq6nGQjcHXaBa1UVV15ZXpSx8qqHdGvRJKZV16wTHI3\nsB34j+lWtWIngX1J7kiyjcW+nJlyTQPrDr5XPMjii85rSTMf45HkNUle98o08E7W3vPxaieB/d30\nfuCxKdYykptxrKzaEf2NJHkQ+FNgBvj7JGerajfwNuAPkvwv8DLwgaq66S98DGO5vlTVuSQnWPwM\n/5eAg1V1fZq1DukPk+xk8V/q54D3T7ec4TT2MR4bgM8mgcVj/m+q6gvTLWlwST4D3AvcleQi8FHg\nYeBEkvcBzwPvnl6Fg1umL/dO+ljxnbGS1LimTt1Ikn6YQS9JjTPoJalxBr0kNc6gl6TGGfSS1DiD\nXpIaZ9BLUuP+D8UEr6sbj4beAAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x118df8f90>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1.73\t0.71\tbuilt Docstrum\n",
      "1.74\t0.01\tfinished analysing page\n",
      "average time: 1.74\n",
      "\n",
      "Done.\n"
     ]
    }
   ],
   "source": [
    "# LINE EXTRACTION TESTING\n",
    "\n",
    "import sys\n",
    "import os\n",
    "from page import Page\n",
    "\n",
    "import cv2\n",
    "import math\n",
    "import numpy\n",
    "import subprocess\n",
    "import os\n",
    "\n",
    "import colors\n",
    "import geometry as g\n",
    "from box import Box\n",
    "import text\n",
    "from dimension import Dimension\n",
    "from stopwatch import Stopwatch\n",
    "import numpy\n",
    "import matplotlib.pyplot as plt\n",
    "import ntpath\n",
    "\n",
    "\n",
    "SHOW_STEPS = True    # change this to false if you just want to see the final output for each page.\n",
    "SAVE_OUTPUT = True\n",
    "SAVE_DOCSTRUM = False\n",
    "\n",
    "inputFolder = os.path.join('images')\n",
    "outputFolder = os.path.join('output')\n",
    "\n",
    "    \n",
    "inputPath = os.path.join(inputFolder, os.listdir(inputFolder)[0])\n",
    "outputPath = os.path.join(outputFolder, os.listdir(inputFolder)[0])\n",
    "\n",
    "page = Page(inputPath, SHOW_STEPS, SAVE_DOCSTRUM)\n",
    "\n",
    "\n",
    "if True:\n",
    "    page.save(outputPath)  # save a copy of what is displayed. Used for getting images for the paper.\n",
    "    \n",
    "page.show((800, 800))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "print(\"%.2f\" %1.237)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n"
     ]
    }
   ],
   "source": [
    "for line in page.lines:\n",
    "    line.group = None\n",
    "\n",
    "for line in page.lines:\n",
    "    print(line.group)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "[                                                                        ]   0%\r"
     ]
    }
   ],
   "source": [
    "#NER VERSION: ADJUSTIVE SEARCHING ORDER\n",
    "import cv2\n",
    "\n",
    "from shapely.geometry import Point            # For checking overlap\n",
    "from shapely.geometry.polygon import Polygon  # For checking overlap\n",
    "from shapely.geometry import MultiPoint       # For checking overlap\n",
    "\n",
    "import progressbar      # For displaying progressbar\n",
    "from time import sleep  # For displaying progressbar\n",
    "\n",
    "#from stopwatch import Stopwatch   # For checking run-time\n",
    "\n",
    "#stopwatch = Stopwatch()\n",
    "\n",
    "image = page.image.copy()\n",
    "\n",
    "EPS = 1e-10\n",
    "group_idx = 0\n",
    "threshold_angle = 1.0\n",
    "threshold_paralldist = 1.7 * 13.0\n",
    "threshold_perpendist = 1.7 * 17.0 #[1.5~1.7]\n",
    "threshold_overlap    = 1.0\n",
    "threshold_early_skip = 100\n",
    "threshold_visualize_line_width = 5\n",
    "\n",
    "SHOW_DETAIL      = False\n",
    "SHOW_VISUAL_STEP = True\n",
    "EARLY_SKIP       = False\n",
    "\n",
    "########\n",
    "# INIT #\n",
    "########\n",
    "# Get lines\n",
    "_my_lines  = page.lines\n",
    "# Remove dots\n",
    "my_lines = []\n",
    "for _my_line in _my_lines:\n",
    "    if(_my_line.start.x-_my_line.end.x==0 and _my_line.start.y-_my_line.end.y==0):\n",
    "        continue\n",
    "    else:\n",
    "        my_lines.append(_my_line)\n",
    "# Sorting lines\n",
    "my_lines.sort(key=lambda line:((line.start.y+line.end.y)/2,(line.start.x+line.end.x)/2))\n",
    "# Lines assigned a group\n",
    "my_lines_in_group = []\n",
    "# Lines not assigned any group yet\n",
    "my_lines_no_group = []\n",
    "for i in range(0,len(my_lines)-1):\n",
    "    my_lines_no_group.append(i)\n",
    "if SHOW_DETAIL: print(\"no_group:\",my_lines_in_group)\n",
    "if SHOW_DETAIL: print(\"in_group:\",my_lines_no_group)\n",
    "# First line, not dot (its index, i)\n",
    "\n",
    "bar = progressbar.ProgressBar(maxval=len(my_lines_no_group), \\\n",
    "            widgets=[progressbar.Bar('=', '[', ']'), ' ', progressbar.Percentage()])\n",
    "progress_idx = 0\n",
    "bar.start()\n",
    "\n",
    "max_loop = len(my_lines)\n",
    "#act_loop = 0\n",
    "\n",
    "for act_loop in xrange(max_loop): # Make sure looked up every lines   \n",
    "    #flag_found_none = True\n",
    "    if ((len(my_lines_in_group) == 0) and (len(my_lines_no_group) == 0)):\n",
    "        break\n",
    "    #test_act_loop = test_act_loop+1\n",
    "    \n",
    "    progress_idx = progress_idx+2 # Update progressbar\n",
    "    bar.update(act_loop)      # Update progressbar\n",
    "    sleep(0.1)    \n",
    "    #######################\n",
    "    # Set the ith element #\n",
    "    #######################\n",
    "    i = -1\n",
    "    if EARLY_SKIP:\n",
    "        early_skip = threshold_early_skip\n",
    "    ## TODO: Since, currently there is no lines in my_lines_in_group queue and lines are remained, find another line as ith element in my_lines_no_group queue with excluding dots. \n",
    "    if(len(my_lines_in_group) == 0):\n",
    "        delta_x_i = 0\n",
    "        delta_y_i = 0\n",
    "        for candidate_line_idx in my_lines_no_group[:]:\n",
    "            x_O_i = my_lines[candidate_line_idx].start.x\n",
    "            y_O_i = page.image.shape[0] - my_lines[candidate_line_idx].start.y\n",
    "            x_F_i = my_lines[candidate_line_idx].end.x\n",
    "            y_F_i = page.image.shape[0] - my_lines[candidate_line_idx].end.y \n",
    "            #delta_x_i = abs(x_F_i - x_O_i)\n",
    "            delta_x_i = float(x_F_i - x_O_i)\n",
    "            #delta_y_i = abs(y_F_i - y_O_i)\n",
    "            delta_y_i = float(y_F_i - y_O_i)\n",
    "            if (delta_x_i != 0 and delta_y_i != 0): # Found!\n",
    "                i = candidate_line_idx\n",
    "                my_lines_no_group.remove(candidate_line_idx)\n",
    "                break\n",
    "    else:\n",
    "        i = my_lines_in_group.pop(0)\n",
    "        \n",
    "    \n",
    "    # TODO: more sophisticated way to break?\n",
    "    if (i == -1):\n",
    "        break\n",
    "    \n",
    "    # Visualize ith element\n",
    "    if SHOW_VISUAL_STEP:\n",
    "        image = page.image.copy()\n",
    "        cv2.line(image, ((my_lines[i].start.x,my_lines[i].start.y)),((my_lines[i].end.x,my_lines[i].end.y)), (0,0,255),threshold_visualize_line_width)\n",
    "        page.display(image, title='Visualization of text-line groupping step')\n",
    "                                                       \n",
    "    # No more lines to search\n",
    "    if (len(my_lines_no_group) == 0):\n",
    "        break\n",
    "    else:\n",
    "        my_lines[i].noise = False  # This assure that dot-wise noise to be excluded from grouping process\n",
    "        #######################\n",
    "        # Set the jth element #\n",
    "        #######################\n",
    "        for j in my_lines_no_group[:]:\n",
    "            if EARLY_SKIP:\n",
    "                if early_skip < 0:\n",
    "                    break\n",
    "            if SHOW_VISUAL_STEP:\n",
    "                cv2.line(image, ((my_lines[j].start.x,my_lines[j].start.y)),((my_lines[j].end.x,my_lines[j].end.y)), (255,0,0),threshold_visualize_line_width)\n",
    "                page.display(image, title='Visualization of text-line groupping step')\n",
    "\n",
    "            sameGroup = False\n",
    "            ################################\n",
    "            # CALCULATE GEOMETRIC FEATURES #\n",
    "            ################################\n",
    "            # Point setting\n",
    "            x_O_i = my_lines[i].start.x\n",
    "            y_O_i = page.image.shape[0] - my_lines[i].start.y\n",
    "            x_F_i = my_lines[i].end.x\n",
    "            y_F_i = page.image.shape[0] - my_lines[i].end.y \n",
    "\n",
    "            x_O_j = my_lines[j].start.x\n",
    "            y_O_j = page.image.shape[0] - my_lines[j].start.y\n",
    "            x_F_j = my_lines[j].end.x\n",
    "            y_F_j = page.image.shape[0] - my_lines[j].end.y\n",
    "\n",
    "            #delta_x_i = abs(x_F_i - x_O_i)\n",
    "            #delta_y_i = abs(y_F_i - y_O_i)\n",
    "            #delta_x_j = abs(x_F_j - x_O_j)\n",
    "            #delta_y_j = abs(y_F_j - y_O_j)\n",
    "            delta_x_i = float(x_F_i - x_O_i)\n",
    "            delta_y_i = float(y_F_i - y_O_i)\n",
    "            delta_x_j = float(x_F_j - x_O_j)\n",
    "            delta_y_j = float(y_F_j - y_O_j)\n",
    "            \n",
    "            \n",
    "            # ith or jth line is dot, so skip it\n",
    "            if (delta_x_j == 0 and delta_y_j == 0):\n",
    "                my_lines_no_group.remove(j)\n",
    "                continue\n",
    "\n",
    "            if SHOW_DETAIL:\n",
    "                print(\"\\n****************************************************************\")\n",
    "                print(\"# of in_group:\",len(my_lines_in_group),my_lines_in_group)\n",
    "                print(\"# of no_group:\",len(my_lines_no_group),my_lines_no_group)\n",
    "                print(i, my_lines[i].points)\n",
    "                print(j, my_lines[j].points)\n",
    "                print(\"i:\",x_O_i,y_O_i,\"-\",x_F_i,y_F_i)\n",
    "                print(\"j:\",x_O_j,y_O_j,\"-\",x_F_j,y_F_j)\n",
    "\n",
    "            # Calculate angle\n",
    "            theta_i_j = math.atan2(delta_y_j,delta_x_j-math.atan2(delta_y_i,delta_x_i))\n",
    "            if SHOW_DETAIL:\n",
    "                print(\"Angle:\",theta_i_j)\n",
    "\n",
    "            # Calculate overlap\n",
    "            #if delta_x_j == 0:\n",
    "            #    delta_x_j = 0.1\n",
    "            #if delta_y_i == 0:\n",
    "            #    delta_y_i = 0.1\n",
    "            #if delta_y_j == 0:\n",
    "            #    delta_y_j = 0.1\n",
    "            #if delta_x_i == 0:\n",
    "            #    delta_x_i = 0.1\n",
    "\n",
    "\n",
    "            x_A_j = (x_O_i*delta_x_i*delta_x_j + x_O_j*delta_y_i*delta_y_j + delta_x_j*delta_y_i*(y_O_i-y_O_j))/(delta_y_i*delta_y_j + delta_x_i*delta_x_j + EPS)\n",
    "            if (delta_x_j != 0):\n",
    "                y_A_j = (delta_y_j/delta_x_j)*(x_A_j - x_O_j) + y_O_j\n",
    "            else:\n",
    "                x_A_j = y_O_j\n",
    "\n",
    "            x_B_j = (x_F_i*delta_x_i*delta_x_j + x_F_j*delta_y_i*delta_y_j + delta_x_j*delta_y_i*(y_F_i-y_F_j))/(delta_y_i*delta_y_j + delta_x_i*delta_x_j + EPS)\n",
    "            if (delta_x_j != 0):\n",
    "                y_B_j = (delta_y_j/delta_x_j)*(x_B_j - x_F_j) + y_F_j\n",
    "            else:\n",
    "                x_B_j = y_F_j\n",
    "\n",
    "            # Find C and D ponts\n",
    "            #x_middle_candidates = [x_O_j, x_F_j, x_A_j, x_B_j]\n",
    "            #x_middle_candidates.sort()\n",
    "            #y_middle_candidates = [y_O_j, y_F_j, y_A_j, y_B_j]\n",
    "            #y_middle_candidates.sort()\n",
    "            C_D_candidates = [(x_O_j,y_O_j), (x_F_j,y_F_j), (x_A_j,y_A_j), (x_B_j,y_B_j)]\n",
    "            if (delta_x_j != 0):\n",
    "                C_D_candidates.sort(key=lambda x:x[0]) # sort by x\n",
    "            elif (delta_y_j != 0):\n",
    "                C_D_candidates.sort(key=lambda x:x[1]) # sort by y\n",
    "            x_C_j,y_C_j = C_D_candidates[1]\n",
    "            x_D_j,y_D_j = C_D_candidates[2]\n",
    "\n",
    "            if SHOW_DETAIL:\n",
    "                print(\"x_A_j,y_A_j\",x_A_j,y_A_j)\n",
    "                print(\"x_B_j,y_B_j\",x_B_j,y_B_j)\n",
    "                print(\"x_C_j,y_C_j\",x_C_j,y_C_j)\n",
    "                print(\"x_D_j,y_D_j\",x_D_j,y_D_j)\n",
    "\n",
    "            #x_i_j_components = [int(x_O_i), int(x_F_i), int(x_O_j), int(x_F_j)]\n",
    "            #x_i_j_components.sort()\n",
    "            #y_i_j_components = [int(y_O_i), int(y_F_i), int(y_O_j), int(y_F_j)]\n",
    "            #y_i_j_components.sort()\n",
    "            # convert to int in order to allow generous overlap\n",
    "            #if ((int(x_O_j) <= int(x_C_j) <= int(x_F_j) and (int(y_O_j) <= int(y_C_j) <= int(y_F_j) or int(y_F_j) <= int(y_C_j) <= int(y_O_j))) or (int(x_O_i) <= int(x_C_j) <= int(x_F_i) and (int(y_O_i) <= int(x_C_j) <= int(y_F_i) or int(y_F_i) <= int(y_C_j) <= int(y_O_i)))) and ((int(x_O_j) <= int(x_D_j) <= int(x_F_j) and (int(y_O_j) <= int(y_D_j) <= int(y_F_j) or int(y_F_j) <= int(y_D_j) <= int(y_O_j))) or (int(x_O_i) <= int(x_D_j) <= int(x_F_i) and (int(y_O_i) <= int(y_D_j) <= int(y_F_i) or int(y_F_i) <= int(y_D_j) <= int(y_O_i)))):\n",
    "            #if ((x_i_j_components[0] <= int(x_C_j[0]) <= x_i_j_components[-1]) and (y_i_j_components[0] <= int(y_C_j) <= y_i_j_components[-1]) and (x_i_j_components[0] <= int(x_D_j) <= x_i_j_components[-1]) and (y_i_j_components[0] <= int(y_D_j) <= y_i_j_components[-1])):\n",
    "            #convex_hull = MultiPoint([(x_O_j, y_O_j), (x_O_j, y_F_j), (x_F_j, y_F_j), (x_F_j, y_O_j)])\n",
    "            #polygon = Polygon([(x_O_i, y_O_i), (x_F_i, y_F_i),(x_F_j, y_F_j), (x_O_j, y_O_j)])\n",
    "            #convex_hull = MultiPoint([(x_O_i, y_O_i), (x_F_i, y_F_i),(x_F_j, y_F_j), (x_O_j, y_O_j)]).convex_hull\n",
    "            polygon = Polygon([(x_O_j, y_O_j), (x_O_j, y_F_j), (x_F_j, y_F_j), (x_F_j, y_O_j)])\n",
    "            C_point = Point(x_C_j, y_C_j)\n",
    "            D_point = Point(x_D_j, y_D_j)\n",
    "            #if polygon.area != convex_hull.area:\n",
    "            #    overlap = False\n",
    "            #elif (convex_hull.contains(C_point) and convex_hull.contains(D_point)):\n",
    "            #if (convex_hull.contains(C_point) and convex_hull.contains(D_point)):\n",
    "            if (polygon.contains(C_point) or polygon.touches(C_point)) and (polygon.contains(D_point) or polygon.touches(D_point)):\n",
    "                overlap = True\n",
    "            else:\n",
    "                overlap = False\n",
    "            \n",
    "            #p_j = (math.sqrt(math.pow(y_D_j-y_C_j,2)+math.pow(x_D_j-x_C_j,2)))/2.0\n",
    "            p_j = math.sqrt(math.pow(y_D_j-y_C_j,2)+math.pow(x_D_j-x_C_j,2))\n",
    "            l_j = math.sqrt(math.pow(y_F_j-y_O_j,2)+math.pow(x_F_j-x_O_j,2))\n",
    "            if (l_j == 0):\n",
    "                l_j = 0.1\n",
    "            if overlap:\n",
    "                p_i_j = p_j/l_j\n",
    "            else:\n",
    "                p_i_j = -p_j/l_j\n",
    "\n",
    "            if SHOW_DETAIL:\n",
    "                print(\"Overlap?\",overlap)\n",
    "                print(\"p_j:\",p_j)\n",
    "                print(\"p_i_j:\",p_i_j)\n",
    "\n",
    "            # Calculate parallel_dist\n",
    "            if overlap:\n",
    "                d_i_j_a = p_j\n",
    "            else:\n",
    "                d_i_j_a = -p_j\n",
    "            if SHOW_DETAIL:\n",
    "                print(\"parallel_dist: \",d_i_j_a)\n",
    "\n",
    "            # Calculate perpend_dist\n",
    "            x_M_j = (x_C_j + x_D_j)/2.0\n",
    "            y_M_j = (y_C_j + y_D_j)/2.0\n",
    "            if SHOW_DETAIL:\n",
    "                print(\"x_M_j,y_M_j\",x_M_j,y_M_j)\n",
    "                print(\"delta_x_i:\",delta_x_i)\n",
    "                print(\"delta_y_i:\",delta_y_i)\n",
    "                print(\"delta_x_j:\",delta_x_j)\n",
    "                print(\"delta_y_j:\",delta_y_j)\n",
    "\n",
    "            if delta_x_i != 0.0 and delta_y_i != 0.0:\n",
    "                d_e_i_j = ((x_M_j - x_O_i) - (y_M_j - y_O_i)*delta_x_i/(delta_y_i + EPS))/((delta_x_i**2)/(delta_y_i**2 + EPS) + 1)**0.5 \n",
    "            elif delta_y_i == 0.0:\n",
    "                d_e_i_j = int(y_M_j) - int(y_O_i)\n",
    "            elif delta_x_i == 0.0:\n",
    "                d_e_i_j = int(x_M_j) - int(x_O_i)\n",
    "            d_e_i_j = abs(d_e_i_j)\n",
    "\n",
    "            if SHOW_DETAIL:\n",
    "                print(\"perpend_dist: \",d_e_i_j)\n",
    "\n",
    "            ######################\n",
    "            # DECIDING GROUPNESS #\n",
    "            #######################\n",
    "            # 1. angle check\n",
    "            if theta_i_j < threshold_angle:\n",
    "                if SHOW_DETAIL: print(\"... Angle ok!\")\n",
    "            # 2. perpend_dist check\n",
    "                if 0 < d_e_i_j < threshold_perpendist:\n",
    "                    if SHOW_DETAIL: print(\"... Perpendicular ok!\")\n",
    "            # 3.a. overlap check\n",
    "            # 3.b. parallel_dist check\n",
    "                    if ((overlap and p_i_j <= threshold_overlap)):\n",
    "                        if SHOW_DETAIL: print(\"... Overlap & p_i_j ok!\")\n",
    "                        # Group!\n",
    "                        sameGroup = True\n",
    "                    elif (abs(d_i_j_a) < threshold_paralldist):\n",
    "                        if SHOW_DETAIL: print(\"... Parallel ok!\")\n",
    "                        # Group!\n",
    "                        sameGroup = True\n",
    "\n",
    "            if SHOW_DETAIL:\n",
    "                print(\"same group? \",sameGroup)\n",
    "            if sameGroup:\n",
    "\n",
    "                if EARLY_SKIP:\n",
    "                    early_skip = threshold_early_skip\n",
    "                if SHOW_DETAIL:\n",
    "                    print(\"before group idx: \",group_idx)\n",
    "                    print(\"before i's group: \", my_lines[i].group)\n",
    "                    print(\"before j's group: \", my_lines[j].group)\n",
    "                if (my_lines[i].group == None) and (my_lines[j].group == None):\n",
    "                    if SHOW_DETAIL:\n",
    "                        print(\"... case 1\")\n",
    "                    # Assign to a new block\n",
    "                    group_idx = group_idx + 1\n",
    "                    my_lines[i].group = group_idx\n",
    "                    my_lines[j].group = group_idx\n",
    "                    #my_lines_no_group.remove(i)     # update queue\n",
    "                    my_lines_in_group.append(i)     # update queue\n",
    "                    my_lines_no_group.remove(j)     # update queue\n",
    "                    my_lines_in_group.append(j)     # update queue\n",
    "                elif (my_lines[i].group == None):\n",
    "                    if SHOW_DETAIL: print(\"... case 2\")\n",
    "                    # Unassigned text-line is assigned to the block of the other\n",
    "                    my_lines[i].group = my_lines[j].group\n",
    "                    #my_lines_no_group.remove(i)     # update queue\n",
    "                    my_lines_in_group.append(i)     # update queue\n",
    "                elif (my_lines[j].group == None):\n",
    "                    if SHOW_DETAIL: print(\"... case 3\")\n",
    "                    # Unassigned text-line is assigned to the block of the other\n",
    "                    my_lines[j].group = my_lines[i].group\n",
    "                    my_lines_no_group.remove(j)     # update queue\n",
    "                    my_lines_in_group.append(j)     # update queue\n",
    "                if SHOW_DETAIL: print(\"after group idx: \",group_idx)\n",
    "                if SHOW_DETAIL: print(\"after i's group: \", my_lines[i].group)\n",
    "                if SHOW_DETAIL: print(\"after j's group: \", my_lines[j].group)\n",
    "                if SHOW_VISUAL_STEP:\n",
    "                    cv2.line(image, ((my_lines[j].start.x,my_lines[j].start.y)),((my_lines[j].end.x,my_lines[j].end.y)), (0,255,0),threshold_visualize_line_width)\n",
    "                    page.display(image, title='Visualization of text-line groupping step')\n",
    "            else:\n",
    "                if EARLY_SKIP:\n",
    "                    early_skip = early_skip - 1\n",
    "            \n",
    "        if (my_lines[i].noise == False and my_lines[i].group == None):\n",
    "            group_idx = group_idx + 1\n",
    "            my_lines[i].group = group_idx\n",
    "bar.finish()\n",
    "\n",
    "print(\"Total iter: [%d/%d]\" %(act_loop,max_loop))\n",
    "print(\"Done!\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "\n",
    "dist = [10,20,20,50,20,20,30,25,25,25,25,25,25]\n",
    "n, bins, patches = plt.hist(dist, numpy.max(dist)-numpy.min(dist)+1, facecolor='orange', alpha=0.5)\n",
    "n_copy = n.copy()\n",
    "print(n)\n",
    "print(n_copy)\n",
    "n_copy[::-1].sort()\n",
    "print(n)\n",
    "print(n_copy)\n",
    "print(bins)\n",
    "print(numpy.argmax(n)+numpy.min(dist))\n",
    "print(bins.max())\n",
    "\n",
    "#n_copy[::-1].sort()\n",
    "a = numpy.where(n == n_copy[2])\n",
    "print(\"Test\",a)\n",
    "\n",
    "if len(a[0])>1:\n",
    "    _max = a[0][int(len(a[0])/2)]\n",
    "else:\n",
    "    _max = a[0][0]\n",
    "\n",
    "_max+numpy.min(dist)\n",
    "\n",
    "for i in range(5):\n",
    "    print(i)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "peakind = signal.find_peaks_cwt([10,20,20,50,20,20,30], np.arange(1,10))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "peakind"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "x_O_i = 491\n",
    "y_O_i = 615\n",
    "x_F_i = 757\n",
    "y_F_i = 600\n",
    "x_O_j = 491\n",
    "y_O_j = 615\n",
    "x_F_j = 757\n",
    "y_F_j = 600\n",
    "x_C_j = 757\n",
    "y_C_j = int(637.6500942238861)\n",
    "\n",
    "delta_y_j = 7.0\n",
    "delta_x_j = 658.0\n",
    "x_A_j = 4144.4503916449075\n",
    "x_F_j = 3890.0\n",
    "y_F_j = 1856.0\n",
    "(delta_y_j/delta_x_j)*(x_A_j - x_F_j) + y_F_j\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "('i:', 2639, 4875, '-', 2676, 4872)\n",
    "('j:', 992, 4892, '-', 2222, 4879)\n",
    "('Angle:', -0.010568017106413556)\n",
    "('x_A_j,y_A_j', 2638.9670025686564, 4874.593031680169)\n",
    "('x_B_j,y_B_j', 2676.178357373372, 4874.19974093833)\n",
    "('x_C_j,y_C_j', 2222, 4879)\n",
    "('x_D_j,y_D_j', 2638.9670025686564, 4874.593031680169)\n",
    "\n",
    "x_O_i = 2639\n",
    "y_O_i = 4875\n",
    "x_F_i = 2676\n",
    "y_F_i = 4872\n",
    "\n",
    "x_O_j = 896\n",
    "y_O_j = 4802\n",
    "x_F_j = 1415\n",
    "y_F_j = 4805\n",
    "\n",
    "x_C_j = 2222\n",
    "y_C_j = 4879\n",
    "x_D_j = 2638#.9670025686564\n",
    "y_D_j = 4874#.593031680169\n",
    "\n",
    "\n",
    "#polygon = Polygon([(x_O_i-1, y_O_i+1), (x_F_i+1, y_F_i+1),(x_F_j+1, y_F_j-1), (x_O_j-1, y_O_j-1)])\n",
    "polygon = Polygon([(x_O_i, y_O_i), (x_F_i, y_F_i),(x_F_j, y_F_j), (x_O_j, y_O_j)])\n",
    "#C_point = Point(x_C_j, y_C_j)\n",
    "#D_point = Point(x_D_j, y_D_j)\n",
    "polygon.area"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "from shapely.geometry import MultiPoint\n",
    "convex_hull = MultiPoint([(x_O_i, y_O_i), (x_F_i, y_F_i),(x_F_j, y_F_j), (x_O_j, y_O_j)]).convex_hull\n",
    "convex_hull.area"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "x_O_j = 2476\n",
    "y_O_j = 1938\n",
    "x_F_j = 2840\n",
    "y_F_j = 1932\n",
    "x_A_j = 2363\n",
    "y_A_j = 1939\n",
    "x_B_j = 2631\n",
    "y_B_j = 1935\n",
    "\n",
    "C_D_candidates = [(x_O_j,y_O_j), (x_F_j,y_F_j), (x_A_j,y_A_j), (x_B_j,y_B_j)]\n",
    "C_D_candidates.sort(key=lambda x:x[0])\n",
    "print(C_D_candidates[1])\n",
    "print(C_D_candidates[2])\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "C_D_candidates"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "C_D_candidates"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "C_x,C_y = C_D_candidates[1]\n",
    "print(C_x)\n",
    "print(C_y)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "Polygon([(0-1, y_O_i+1), (x_F_i+1, y_F_i+1),(x_F_j+1, y_F_j-1), (x_O_j-1, y_O_j-1)])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "######################\n",
    "# Draw Grouped Lines #\n",
    "######################\n",
    "import cv2\n",
    "image = page.image.copy()\n",
    "for my_line in my_lines:\n",
    "    #print(my_line.start.x)\n",
    "#    print my_line.group\n",
    "    if my_line.group == None:\n",
    "        continue\n",
    "        blue  = 0\n",
    "        green = 0 \n",
    "        red   = 0\n",
    "    else:\n",
    "        blue = (my_line.group*100)%255\n",
    "        green = (my_line.group*200)%255\n",
    "        red = (my_line.group*300)%255\n",
    "        \n",
    "    #print(blue,green,red)\n",
    "    cv2.line(image, (my_line.start.x,my_line.start.y), (my_line.end.x,my_line.end.y), (blue,green,red),10)\n",
    "    \n",
    "#cv2.imwrite(outputPath, image) \n",
    "maxDimension = Dimension(800, 800)\n",
    "displayDimension = Dimension(image.shape[1], image.shape[0])\n",
    "displayDimension.fitInside(maxDimension)\n",
    "image = cv2.resize(image, tuple(displayDimension))\n",
    "cv2.namedWindow('title', cv2.CV_WINDOW_AUTOSIZE)\n",
    "cv2.imshow('grouped', image)\n",
    "cv2.waitKey()\n",
    "cv2.destroyAllWindows()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "#######################\n",
    "# Draw Bounding Boxes #\n",
    "#######################\n",
    "import cv2\n",
    "import numpy\n",
    "THRESHOLD_POLY_EXAGGERATE = 10 # Unit: Pixel\n",
    "image = page.image.copy()\n",
    "tot_groups = group_idx+1\n",
    "group_table = []\n",
    "for group_idx in range(tot_groups):\n",
    "    group_table.append([])\n",
    "\n",
    "for my_line in my_lines:\n",
    "    for group_idx in range(1,tot_groups):\n",
    "        if my_line.group == None:\n",
    "            continue\n",
    "        elif my_line.group == group_idx:\n",
    "            exaggerated_left_start_x   = my_line.start.x-THRESHOLD_POLY_EXAGGERATE\n",
    "            exaggerated_up_start_y     = my_line.start.y+THRESHOLD_POLY_EXAGGERATE\n",
    "            exaggerated_down_start_y   = my_line.start.y-THRESHOLD_POLY_EXAGGERATE\n",
    "            \n",
    "            exaggerated_right_end_x    = my_line.end.x+THRESHOLD_POLY_EXAGGERATE\n",
    "            exaggerated_up_end_y       = my_line.end.y+THRESHOLD_POLY_EXAGGERATE\n",
    "            exaggerated_down_end_y     = my_line.end.y-THRESHOLD_POLY_EXAGGERATE\n",
    "            \n",
    "            group_table[group_idx-1].append([exaggerated_left_start_x,exaggerated_up_start_y])\n",
    "            group_table[group_idx-1].append([exaggerated_left_start_x,exaggerated_down_start_y])\n",
    "            \n",
    "            group_table[group_idx-1].append([exaggerated_right_end_x,exaggerated_up_end_y])\n",
    "            group_table[group_idx-1].append([exaggerated_right_end_x,exaggerated_down_end_y])\n",
    "            \n",
    "            \n",
    "\n",
    "for group_idx in range(1,tot_groups):\n",
    "    points = numpy.array(group_table[group_idx-1], dtype='int')\n",
    "    rect = cv2.minAreaRect(points)\n",
    "    box = cv2.cv.BoxPoints(rect) # cv2.boxPoints(rect) for OpenCV 3.x\n",
    "    box = numpy.int0(box)\n",
    "    cv2.drawContours(image,numpy.int32([box]),0,(0,0,255),7)\n",
    "    #convex_hull = cv2.convexHull(points)\n",
    "    #cv2.polylines(image, numpy.int32([convex_hull]), True, (0, 0, 255), thickness=2)\n",
    "\n",
    "\n",
    "maxDimension = Dimension(800, 800)\n",
    "displayDimension = Dimension(image.shape[1], image.shape[0])\n",
    "displayDimension.fitInside(maxDimension)\n",
    "image = cv2.resize(image, tuple(displayDimension))\n",
    "cv2.namedWindow('Polylines', cv2.CV_WINDOW_AUTOSIZE)\n",
    "cv2.imshow('Polylines', image)\n",
    "cv2.waitKey()\n",
    "cv2.destroyAllWindows()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "cv2.imwrite(outputPath, image)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "group_table"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "cv2.imwrite(outputPath, image)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "################################\n",
    "# Draw BoundingBox (Rectangle) #\n",
    "################################\n",
    "import cv2\n",
    "import numpy\n",
    "image = page.image.copy()\n",
    "boundingbox_table = numpy.zeros((group_idx+1,4))  # [min_x,max_x,min_y,max_y]\n",
    "boundingbox_table[:,0] = image.shape[1]\n",
    "boundingbox_table[:,1] = 0\n",
    "boundingbox_table[:,2] = image.shape[0]\n",
    "boundingbox_table[:,3] = 0\n",
    "\n",
    "# Find BoundingBoxes for Each Group\n",
    "for my_line in my_lines:\n",
    "    for i in range(1,group_idx+1):\n",
    "        if my_line.group == None:\n",
    "            # Update if found new min or max\n",
    "            if my_line.start.x < boundingbox_table[-1,0]:\n",
    "                boundingbox_table[-1,0] = my_line.start.x\n",
    "            if my_line.end.x > boundingbox_table[-1,1]:\n",
    "                boundingbox_table[-1,1] = my_line.end.x\n",
    "            if my_line.start.y < boundingbox_table[-1,2]:\n",
    "                boundingbox_table[-1,2] = my_line.start.y\n",
    "            if my_line.end.y > boundingbox_table[-1,3]:\n",
    "                boundingbox_table[-1,3] = my_line.end.y\n",
    "        elif my_line.group == i:\n",
    "            # Update if found new min or max\n",
    "            if my_line.start.x < boundingbox_table[i-1,0]:\n",
    "                boundingbox_table[i-1,0] = my_line.start.x\n",
    "            if my_line.end.x > boundingbox_table[i-1,1]:\n",
    "                boundingbox_table[i-1,1] = my_line.end.x\n",
    "            if my_line.start.y < boundingbox_table[i-1,2]:\n",
    "                boundingbox_table[i-1,2] = my_line.start.y\n",
    "            if my_line.end.y > boundingbox_table[i-1,3]:\n",
    "                boundingbox_table[i-1,3] = my_line.end.y\n",
    "                \n",
    "# Draw BoundingBoxes \n",
    "for i in range(group_idx+1):\n",
    "    x_min = int(boundingbox_table[i,0])\n",
    "    x_max = int(boundingbox_table[i,1])\n",
    "    y_min = int(boundingbox_table[i,2])\n",
    "    y_max = int(boundingbox_table[i,3])\n",
    "    cv2.rectangle(image,(x_min,y_max),(x_max,y_min),(0,0,255),5) # (image, Top-Left, Bottom-Right, BGR_Color, Width)\n",
    "\n",
    "\n",
    "maxDimension = Dimension(800, 800)\n",
    "displayDimension = Dimension(image.shape[1], image.shape[0])\n",
    "displayDimension.fitInside(maxDimension)\n",
    "image = cv2.resize(image, tuple(displayDimension))\n",
    "cv2.namedWindow('title', cv2.CV_WINDOW_AUTOSIZE)\n",
    "cv2.imshow('grouped', image)\n",
    "cv2.waitKey()\n",
    "cv2.destroyAllWindows()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "cv2.imwrite(outputPath, image)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "############################\n",
    "############################\n",
    "############################\n",
    "############################\n",
    "#### LEGACY CODES BELOW ####\n",
    "############################\n",
    "############################\n",
    "############################\n",
    "############################"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "#WORKING OLD VERSION: BUT CLUSMY RESULT\n",
    "#from __future__ import division\n",
    "#i=0\n",
    "#j=5\n",
    "\n",
    "SHOW_DETAIL = True\n",
    "SHOW_DETAIL = True\n",
    "\n",
    "# Sorting lines\n",
    "my_lines = page.lines\n",
    "my_lines.sort(key=lambda line:((line.start.y+line.end.y)/2,(line.start.x+line.end.x)/2))\n",
    "#my_lines[0].start.x = 2\n",
    "#my_lines[0].start.y = 0\n",
    "#my_lines[0].end.x = 6\n",
    "#my_lines[0].end.y = 0\n",
    "\n",
    "#my_lines[5].start.x = 1\n",
    "#my_lines[5].start.y = 1\n",
    "#my_lines[5].end.x = 5\n",
    "#my_lines[5].end.y = 3\n",
    "\n",
    "#my_lines[0].group = None\n",
    "#my_lines[5].group = None\n",
    "\n",
    "EPS = 3#1e-3\n",
    "group_idx = 0\n",
    "threshold_angle = 1.0\n",
    "threshold_perpendist = 1.3 * 60.0\n",
    "threshold_overlap    = 1.0\n",
    "threshold_paralldist = 1.5 * 40.0\n",
    "\n",
    "for idx_my_line, my_line in enumerate(my_lines):\n",
    "    if(idx_my_line+1 == len(my_lines)-1):\n",
    "        break\n",
    "    i = idx_my_line\n",
    "    for j in range(i+1,len(my_lines)-1):\n",
    "    #for j in range(i+1,30):\n",
    "        sameGroup = False\n",
    "        ################################\n",
    "        # CALCULATE GEOMETRIC FEATURES #\n",
    "        ################################\n",
    "        # Point setting\n",
    "        x_O_i = my_lines[i].start.x\n",
    "        #y_O_i = my_lines[i].start.y\n",
    "        y_O_i = page.image.shape[0] - my_lines[i].start.y\n",
    "        x_F_i = my_lines[i].end.x\n",
    "        #y_F_i = my_lines[i].end.y\n",
    "        y_F_i = page.image.shape[0] - my_lines[i].end.y \n",
    "\n",
    "        x_O_j = my_lines[j].start.x\n",
    "        #y_O_j = my_lines[j].start.y\n",
    "        y_O_j = page.image.shape[0] - my_lines[j].start.y\n",
    "        x_F_j = my_lines[j].end.x\n",
    "        #y_F_j = my_lines[j].end.y\n",
    "        y_F_j = page.image.shape[0] - my_lines[j].end.y\n",
    "        \n",
    "        delta_x_i = abs(x_F_i - x_O_i)\n",
    "        delta_y_i = abs(y_F_i - y_O_i)\n",
    "        delta_x_j = abs(x_F_j - x_O_j)\n",
    "        delta_y_j = abs(y_F_j - y_O_j)\n",
    "        \n",
    "        # ith or jth line is dot, so skip it\n",
    "        if ((delta_x_i == 0 and delta_y_i == 0) or (delta_x_j == 0 and delta_y_j == 0)):\n",
    "            continue\n",
    "            \n",
    "        if SHOW_DETAIL:\n",
    "            print(\"\\n****************************************************************\")\n",
    "            print(i, my_lines[i].points)\n",
    "            print(j, my_lines[j].points)\n",
    "            print(\"i:\",x_O_i,y_O_i,\"-\",x_F_i,y_F_i)\n",
    "            print(\"j:\",x_O_j,y_O_j,\"-\",x_F_j,y_F_j)\n",
    "            \n",
    "        # Calculate angle\n",
    "        theta_i_j = math.atan2(delta_y_j,delta_x_j-math.atan2(delta_y_i,delta_x_i))\n",
    "        if SHOW_DETAIL:\n",
    "            print(\"Angle:\",theta_i_j)\n",
    "\n",
    "        # Calculate overlap\n",
    "        #if delta_x_j == 0:\n",
    "        #    delta_x_j = 0.1\n",
    "        #if delta_y_i == 0:\n",
    "        #    delta_y_i = 0.1\n",
    "        #if delta_y_j == 0:\n",
    "        #    delta_y_j = 0.1\n",
    "        #if delta_x_i == 0:\n",
    "        #    delta_x_i = 0.1\n",
    "\n",
    "\n",
    "        x_A_j = (x_O_i*delta_x_i*delta_x_j + x_O_j*delta_y_i*delta_y_j + delta_x_j*delta_y_i*(y_O_i-y_O_j))/(delta_y_i*delta_y_j + delta_x_i*delta_x_j + EPS)\n",
    "        if (delta_x_j != 0):\n",
    "            y_A_j = (delta_y_j/delta_x_j)*(x_A_j - x_O_j) + y_O_j\n",
    "        else:\n",
    "            x_A_j = y_O_j\n",
    "\n",
    "        x_B_j = (x_F_i*delta_x_i*delta_x_j + x_F_j*delta_y_i*delta_y_j + delta_x_j*delta_y_i*(y_F_i-y_F_j))/(delta_y_i*delta_y_j + delta_x_i*delta_x_j + EPS)\n",
    "        if (delta_x_j != 0):\n",
    "            y_B_j = (delta_y_j/delta_x_j)*(x_A_j - x_F_j) + y_F_j\n",
    "        else:\n",
    "            x_B_j = y_F_j\n",
    "\n",
    "        x_middle_candidates = [x_O_j, x_F_j, x_A_j, x_B_j]\n",
    "        x_middle_candidates.sort()\n",
    "        y_middle_candidates = [y_O_j, y_F_j, y_A_j, y_B_j]\n",
    "        y_middle_candidates.sort()\n",
    "\n",
    "        x_C_j = x_middle_candidates[-2]\n",
    "        y_C_j = y_middle_candidates[-2]\n",
    "\n",
    "        x_D_j = x_middle_candidates[-3]\n",
    "        y_D_j = y_middle_candidates[-3]\n",
    "        if SHOW_DETAIL:\n",
    "            print(\"x_A_j,y_A_j\",x_A_j,y_A_j)\n",
    "            print(\"x_B_j,y_B_j\",x_B_j,y_B_j)\n",
    "            print(\"x_C_j,y_C_j\",x_C_j,y_C_j)\n",
    "            print(\"x_D_j,y_D_j\",x_D_j,y_D_j)\n",
    "\n",
    "        if ((x_O_j <= x_C_j <= x_F_j and y_O_j <= y_C_j <= y_F_j) or (x_O_i <= x_C_j <= x_F_i and y_O_i <= x_C_j <= y_F_i)) and ((x_O_j <= x_D_j <= x_F_j and y_O_j <= y_D_j <= y_F_j) or (x_O_i <= x_D_j <= x_F_i and y_O_i <= y_D_j <= y_F_i)):\n",
    "            overlap = True\n",
    "        else:\n",
    "            overlap = False\n",
    "        # Force to be true; no overlap is required in the default mode\n",
    "        #overlap = True\n",
    "\n",
    "        p_j = (math.sqrt(math.pow(y_D_j-y_C_j,2)+math.pow(x_D_j-x_C_j,2)))/2.0\n",
    "        l_j = math.sqrt(math.pow(y_F_j-y_O_j,2)+math.pow(x_F_j-x_O_j,2))\n",
    "        if (l_j == 0):\n",
    "            l_j = 0.1\n",
    "        if overlap:\n",
    "            p_i_j = p_j/l_j\n",
    "        else:\n",
    "            p_i_j = -p_j/l_j\n",
    "        \n",
    "        if SHOW_DETAIL:\n",
    "            print(\"Overlap?\",overlap)\n",
    "            print(\"p_j:\",p_j)\n",
    "            print(\"p_i_j:\",p_i_j)\n",
    "\n",
    "        # Calculate parallel_dist\n",
    "        if overlap:\n",
    "            d_i_j_a = p_j\n",
    "        else:\n",
    "            d_i_j_a = -p_j\n",
    "        if SHOW_DETAIL:\n",
    "            print(\"parallel_dist: \",d_i_j_a)\n",
    "\n",
    "        # Calculate perpend_dist\n",
    "        x_M_j = (x_C_j + x_D_j)/2.0\n",
    "        y_M_j = (y_C_j + y_D_j)/2.0\n",
    "        if SHOW_DETAIL:\n",
    "            print(\"x_M_j,y_M_j\",x_M_j,y_M_j)\n",
    "            print(\"delta_x_i:\",delta_x_i)\n",
    "            print(\"delta_y_i:\",delta_y_i)\n",
    "            print(\"delta_x_j:\",delta_x_j)\n",
    "            print(\"delta_y_j:\",delta_y_j)\n",
    "            \n",
    "        if delta_x_i != 0.0 and delta_x_i != 0.0:\n",
    "            d_e_i_j = ((x_M_j - x_O_i) - (y_M_j - y_O_i)*delta_x_i/(delta_y_i + EPS))/((delta_x_i**2)/(delta_y_i**2 + EPS) + 1)**0.5\n",
    "            #((x_M_j - x_O_i) - (y_M_j - y_O_i)*delta_x_i/(delta_y_i + EPS))/(math.pow(math.pow(delta_x_i,2)/math.pow(delta_y_i,2)+1,0.5) + EPS)\n",
    "        elif delta_y_i == 0.0:\n",
    "            d_e_i_j = y_M_j - y_O_i  \n",
    "        elif delta_x_i == 0.0:\n",
    "            d_e_i_j = x_M_j - x_O_i\n",
    "        d_e_i_j = abs(d_e_i_j)\n",
    "        \n",
    "        if SHOW_DETAIL:\n",
    "            print(\"perpend_dist: \",d_e_i_j)\n",
    "\n",
    "        ######################\n",
    "        # DECIDING GROUPNESS #\n",
    "        #######################\n",
    "        # 1. angle check\n",
    "        if theta_i_j < threshold_angle:\n",
    "            if SHOW_DETAIL: print(\"... Angle ok!\")\n",
    "        # 2. perpend_dist check\n",
    "            if 0 < d_e_i_j < threshold_perpendist:\n",
    "                if SHOW_DETAIL: print(\"... Perpendicular ok!\")\n",
    "        # 3.a. overlap check\n",
    "        # 3.b. parallel_dist check\n",
    "                if ((overlap and p_i_j < threshold_overlap)):\n",
    "                    if SHOW_DETAIL: print(\"... Overlap & p_i_j ok!\")\n",
    "                    # Group!\n",
    "                    sameGroup = True\n",
    "                elif (abs(d_i_j_a) < threshold_paralldist):\n",
    "                    if SHOW_DETAIL: print(\"... Parallel ok!\")\n",
    "                    # Group!\n",
    "                    sameGroup = True\n",
    "                    \n",
    "        if SHOW_DETAIL:\n",
    "            print(\"same group? \",sameGroup)\n",
    "        if sameGroup:\n",
    "            if SHOW_DETAIL:\n",
    "                print(\"before group idx: \",group_idx)\n",
    "                print(\"before i's group: \", my_lines[i].group)\n",
    "                print(\"before j's group: \", my_lines[j].group)\n",
    "            if (my_lines[i].group == None) and (my_lines[j].group == None):\n",
    "                if SHOW_DETAIL:\n",
    "                    print(\"... case 1\")\n",
    "                # Assign to a new block\n",
    "                group_idx = group_idx + 1\n",
    "                my_lines[i].group = group_idx\n",
    "                my_lines[j].group = group_idx\n",
    "            elif (my_lines[i].group == None):\n",
    "                if SHOW_DETAIL: print(\"... case 2\")\n",
    "                # Unassigned text-line is assigned to the block of the other\n",
    "                my_lines[i].group = my_lines[j].group\n",
    "            elif (my_lines[j].group == None):\n",
    "                if SHOW_DETAIL: print(\"... case 3\")\n",
    "                # Unassigned text-line is assigned to the block of the other\n",
    "                my_lines[j].group = my_lines[i].group\n",
    "            if SHOW_DETAIL: print(\"after group idx: \",group_idx)\n",
    "            if SHOW_DETAIL: print(\"after i's group: \", my_lines[i].group)\n",
    "            if SHOW_DETAIL: print(\"after j's group: \", my_lines[j].group)\n",
    "            #else:\n",
    "                # Block merge\n",
    "\n",
    "print(\"Done!\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "##############################\n",
    "# Draw BoundingBox (Polygon) #\n",
    "##############################\n",
    "import cv2\n",
    "import numpy\n",
    "image = page.image.copy()\n",
    "# point_0 (x_0, y_0) x_0:*    y_0:Max\n",
    "# point_1 (x_1, y_1) x_1:Max  y_1:*\n",
    "# point_2 (x_2, y_2) x_2:*    y_2:Min\n",
    "# point_3 (x_3, y_3) x_3:Min  y_3:*\n",
    "boundingbox_table = numpy.zeros((group_idx+1,8))  # [x_0,y_0,x_1,y_1,x_2,y_2,x_3,y_3]\n",
    "boundingbox_table[:,0] = 0  # x_0\n",
    "boundingbox_table[:,1] = 0  # y_0\n",
    "boundingbox_table[:,2] = 0  # x_1\n",
    "boundingbox_table[:,3] = 0  # y_1\n",
    "boundingbox_table[:,4] = 0  # x_2\n",
    "boundingbox_table[:,5] = image.shape[0]  # y_2\n",
    "boundingbox_table[:,6] = image.shape[1]  # x_3\n",
    "boundingbox_table[:,7] = 0  # y_3\n",
    "\n",
    "# Find BoundingBoxes for Each Group\n",
    "for my_line in my_lines:\n",
    "    for i in range(1,group_idx+1):\n",
    "        \n",
    "                \n",
    "        if my_line.group == i:\n",
    "            # Update if found new min or max\n",
    "            if my_line.start.y > boundingbox_table[i-1,1]:\n",
    "                boundingbox_table[i-1,0] = my_line.start.x\n",
    "                boundingbox_table[i-1,1] = my_line.start.y\n",
    "            if my_line.end.y > boundingbox_table[i-1,1]:\n",
    "                boundingbox_table[i-1,0] = my_line.end.x\n",
    "                boundingbox_table[i-1,1] = my_line.end.y\n",
    "                \n",
    "            if my_line.start.x > boundingbox_table[i-1,2]:\n",
    "                boundingbox_table[i-1,2] = my_line.start.x\n",
    "                boundingbox_table[i-1,3] = my_line.start.y\n",
    "            if my_line.end.y > boundingbox_table[i-1,2]:\n",
    "                boundingbox_table[i-1,2] = my_line.end.x\n",
    "                boundingbox_table[i-1,3] = my_line.end.y\n",
    "                \n",
    "            if my_line.start.y < boundingbox_table[i-1,5]:\n",
    "                boundingbox_table[i-1,4] = my_line.start.x\n",
    "                boundingbox_table[i-1,5] = my_line.start.y\n",
    "            if my_line.end.y < boundingbox_table[i-1,5]:\n",
    "                boundingbox_table[i-1,4] = my_line.end.x\n",
    "                boundingbox_table[i-1,5] = my_line.end.y\n",
    "                \n",
    "            if my_line.start.x < boundingbox_table[i-1,6]:\n",
    "                boundingbox_table[i-1,6] = my_line.start.x\n",
    "                boundingbox_table[i-1,7] = my_line.start.y\n",
    "            if my_line.end.x < boundingbox_table[i-1,6]:\n",
    "                boundingbox_table[i-1,6] = my_line.end.x\n",
    "                boundingbox_table[i-1,7] = my_line.end.y\n",
    "\n",
    "# Draw BoundingBoxes \n",
    "for i in range(group_idx+1):\n",
    "    x_0 = int(boundingbox_table[i,0])\n",
    "    y_0 = int(boundingbox_table[i,1])\n",
    "    x_1 = int(boundingbox_table[i,2])\n",
    "    y_1 = int(boundingbox_table[i,3])\n",
    "    x_2 = int(boundingbox_table[i,4])\n",
    "    y_2 = int(boundingbox_table[i,5])\n",
    "    x_3 = int(boundingbox_table[i,6])\n",
    "    y_3 = int(boundingbox_table[i,7])\n",
    "    \n",
    "    pts = numpy.array([[x_0,y_0],[x_1,y_1],[x_2,y_2],[x_3,y_3]], numpy.int32)\n",
    "    pts = pts.reshape((-1,1,2))\n",
    "    cv2.polylines(image,[pts],True,(0,0,255),5)\n",
    "\n",
    "maxDimension = Dimension(800, 800)\n",
    "displayDimension = Dimension(image.shape[1], image.shape[0])\n",
    "displayDimension.fitInside(maxDimension)\n",
    "image = cv2.resize(image, tuple(displayDimension))\n",
    "cv2.namedWindow('title', cv2.CV_WINDOW_AUTOSIZE)\n",
    "cv2.imshow('grouped', image)\n",
    "cv2.waitKey()\n",
    "cv2.destroyAllWindows()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
